package com.yixing.tech.wcs.service.impl;

import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.hikservice.rcs.RCSResponse;
import com.yixing.tech.common.hikservice.rcs.RCSTaskRequest;
import com.yixing.tech.common.hikservice.rcs.RCSUtil;
import com.yixing.tech.wcs.domain.po.PodInteraction;
import com.yixing.tech.wcs.domain.po.SubTask;
import com.yixing.tech.wcs.service.IBoxTaskService;
import com.yixing.tech.wcs.service.ICRUDService;
import com.yixing.tech.wcs.service.ITaskService;
import com.yixing.tech.wcs.tcp.InteractionState;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.assertj.core.util.Lists;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class BoxTaskService implements IBoxTaskService {

    public static final Map<String, InteractionState> podInteractionStateMap = new ConcurrentHashMap<>();

    @Resource
    private ICRUDService crudService;

    @Resource
    private ITaskService taskService;

    private static final String PUT_DOWN_RESOURCE = "putDown";

    private static final String TAKE_OUT_RESOURCE = "takeOut";

    @Override
    @PostConstruct
    public void loadBoxInteractionState() throws BusinessException {
        List<PodInteraction> podInteractionList = crudService.listPodInteraction();
        for(PodInteraction podInteraction: podInteractionList) {
            podInteractionStateMap.put(podInteraction.getPodCode(), InteractionState.getByDictId(podInteraction.getInteractionState()));
        }
        log.info("加载料箱交互状态:{}", podInteractionStateMap);
    }

    /** CTU申请放下料箱 */
    @Override
    @Async
    public void ctuApplyPutDownBox(String podCode) throws BusinessException {
        // 更新料箱状态为 “准备放下料箱”
        updateBoxInteractionState(podCode, InteractionState.PREPARED);

    }

    /** 设备允许放下料箱 */
    @Override
    @Async
    public void enablePutDown() throws BusinessException {
        // 查询 状态为“准备放下”的料箱号
        for(Map.Entry<String, InteractionState> entry: podInteractionStateMap.entrySet()) {
            if(InteractionState.PREPARED.equals(entry.getValue())) {

                // 查询料箱对应的正在执行中的任务编号
                SubTask subTask = crudService.findExecutingSubTaskOutBoundOneByPodCode(entry.getKey());
                if(ObjectUtils.isNotEmpty(subTask)) {
                    try {
                        synchronized (PUT_DOWN_RESOURCE) {
                            InteractionState state = podInteractionStateMap.get(entry.getKey());
                            if(InteractionState.PREPARED.equals(state)) {
                                log.info("调度CTU放下料箱:taskCode[{}]", subTask.getTaskCode());

                                RCSTaskRequest request = RCSTaskRequest.builder()
                                        .reqCode(UUID.randomUUID().toString().replace("-", "").trim())
                                        .taskCode(subTask.getTaskCode())
                                        .type("2")
                                        .build();

                                RCSResponse response = RCSUtil.boxApplyPass(request);
                                log.info("调度CTU放下料箱结果:{}", response);

                                Thread.sleep(2000);
                            }
                        }
                    } catch (InterruptedException e) {
                        log.error("睡眠被打断");
                    }
                }else {
                    log.info("未找到料箱交互状态:podCode[{}]", entry.getKey());
                }
            }
        }

    }

    @Override
    @Async
    public void ctuOutBoundTaskFinish(String podCode) throws BusinessException {
        // 更新料箱状态为 “放下料箱”
        log.info("更新料箱状态为:放下料箱");
        updateBoxInteractionState(podCode, InteractionState.PUT_DOWN_FINISHED);
    }

    /** 设备回复收到料箱放下信息 */
    @Override
    @Async
    public void replyPutDownFin() throws BusinessException {
        // 查询状态为 “放下料箱”的 料箱交互记录
        for(Map.Entry<String, InteractionState> entry: podInteractionStateMap.entrySet()) {
            // 更新料箱状态为 "放下料箱通知"
            if(InteractionState.PUT_DOWN_FINISHED.equals(entry.getValue())) {
                updateBoxInteractionState(entry.getKey(), InteractionState.PUT_DOWN_NOTIFIED);
            }
        }
    }

    @Override
    @Async
    public void boxHandlingFinish(String podCode) throws BusinessException {
        // 更新料箱状态为 “料箱完成处理”
        updateBoxInteractionState(podCode, InteractionState.HANDLING_FINISHED);
    }

    // 设备回复收到料箱处理完成通知
    @Override
    @Async
    public void replyBoxHandlingFin() throws BusinessException {
        // 查询状态为 “料箱处理完成”的 料箱交互记录
        for(Map.Entry<String, InteractionState> entry: podInteractionStateMap.entrySet()) {
            // 更新料箱状态为 "料箱处理完成通知"
            if(InteractionState.HANDLING_FINISHED.equals(entry.getValue())) {
                updateBoxInteractionState(entry.getKey(), InteractionState.HANDLING_NOTIFIED);
            }
        }
    }

    @Override
    @Async
    public void ctuApplyTakeOutBox(String podCode) throws BusinessException {
        // 更新料箱状态为 "准备取出"
        updateBoxInteractionState(podCode, InteractionState.PREPARED_TAKE_OUT);
    }

    static HashSet<String> handledTaskCodeSet = new HashSet<>();

    /** 设备允许取出料箱 */
    @Override
    @Async
    public void enableTakeOut(String podCode) throws BusinessException {
        // 查询 状态为“准备取出”的料箱号
        for(Map.Entry<String, InteractionState> entry: podInteractionStateMap.entrySet()) {
            if(InteractionState.PREPARED_TAKE_OUT.equals(entry.getValue())) {

                // 查询料箱对应的正在执行中的任务编号
                SubTask subTask = crudService.findExecutingSubTaskInBoundOneByPodCode(entry.getKey());
                log.info("调度CTU取出料箱查询到的任务信息:{}",subTask);
                if(ObjectUtils.isNotEmpty(subTask)) {

                    if(handledTaskCodeSet.contains(subTask.getTaskCode())) {
                        continue;
                    }

                    try {
                        synchronized (TAKE_OUT_RESOURCE) {
                            log.info("准备调度CTU取出料箱:{}", subTask);
                            InteractionState state = podInteractionStateMap.get(entry.getKey());
                            if(InteractionState.PREPARED_TAKE_OUT.equals(state)) {
                                log.info("调度CTU取出料箱:taskCode[{}]", subTask.getTaskCode());

                                RCSTaskRequest request = RCSTaskRequest.builder()
                                        .reqCode(UUID.randomUUID().toString().replace("-", "").trim())
                                        .taskCode(subTask.getTaskCode())
                                        .type("1")
                                        .build();

                                RCSResponse response = RCSUtil.boxApplyPass(request);
                                log.info("调度CTU取出料箱结果:{}", response);

                                if(RCSResponse.SUCCESS.equals(response.getCode())) {
                                    handledTaskCodeSet.add(subTask.getTaskCode());
                                }
                                Thread.sleep(10000);
                            }
                        }
                    } catch (InterruptedException e) {
                        log.error("睡眠被打断");
                    }
                }else {
                    log.info("未找到料箱交互状态:podCode[{}]", entry.getKey());
                }
            }
        }
    }

    @Override
    public void ctuBoxTakeOutFinish(String podCode) throws BusinessException {
        // 更新料箱状态为 "完成取出"
        log.info("更新料箱状态为:podCode[{}], state[{}]", podCode, "完成取出");
        updateBoxInteractionState(podCode, InteractionState.PICK_UP_FINISHED);
    }

    /** 设备回复收到完成取出信息 */
    @Override
    @Async
    public void replyTakeOutFin() throws BusinessException {
        // 查询状态为 “完成取出”的 料箱交互记录
        for(Map.Entry<String, InteractionState> entry: podInteractionStateMap.entrySet()) {
            // 更新料箱状态为 "完成取出通知"
            if(InteractionState.PICK_UP_FINISHED.equals(entry.getValue())) {
                updateBoxInteractionState(entry.getKey(), InteractionState.PICK_UP_NOTIFIED);
            }
        }
    }

    @Override
    public void updateBoxState(String podCode, String interactionStateDictId) throws BusinessException {
        InteractionState interactionState = InteractionState.getByDictId(interactionStateDictId);
        updateBoxInteractionState(podCode, interactionState);
    }


    private void updateBoxInteractionState(String podCode, InteractionState interactionState) {
        if(!podInteractionStateMap.containsKey(podCode)) {
            createBoxInteractionState(podCode, interactionState.getDictId());
            log.info("新增料箱交互状态记录:podCode[{}],state[{}]", podCode, interactionState);
        }

        podInteractionStateMap.put(podCode, interactionState);
        crudService.updatePodInteractionState(Lists.newArrayList(podCode), interactionState.getDictId());

        if(InteractionState.PICK_UP_NOTIFIED.equals(interactionState)) {
            removeBoxInteractionState(podCode);
            log.info("删除料箱交互状态记录:podCode[{}]", podCode);

            podInteractionStateMap.remove(podCode);
        }

        log.info("料箱交互状态更新:{}", podInteractionStateMap);
    }

    private void createBoxInteractionState(String podCode, String state) {
        PodInteraction podInteraction = new PodInteraction();
        podInteraction.setPodCode(podCode);
        podInteraction.setInteractionState(state);
        crudService.addPodInteraction(podInteraction);
    }

    private void removeBoxInteractionState(String podCode) {
        crudService.deletePodInteraction(Lists.newArrayList(podCode));
    }
}
